<?php


namespace Aoe\Intent;


use Aoe\Intent\Request\Request;
use Aoe\Util\Logger\Logger;
use Aoe\Util\Logger\NameRecorder;
use Throwable;

/**
 * # 记录响应结果
 *  HTTP----> HTML
 *    |-----> FILE
 *    |-----> JSON  ----> AJAX
 *              |-------> PJAX
 */
class Response
{
    /**
     * @var ?NameRecorder 日志记录器
     */
    protected ?NameRecorder $recorder = null;
    protected int $trace_level = Logger::ALL;

    /**
     * @var bool 请求处理完成
     */
    private(set) bool $completed = false {
        get {
            return $this->completed;
        }
    }

    /**
     * @var ?string
     */
    public ?string $render = null {
        get {
            if (!$this->render) $this->render = $this->request->getDefaultRender();
            return $this->render;
        }
    }
    
    /**
     * @var bool 结果状态
     */
    protected(set) bool $error = false {
        get {
            return $this->error;
        }
    }
    /**
     * @var bool 抛出异常
     */
    protected bool $exception = false;
    /**
     * @var bool 重定向地址
     */
    protected bool $redirect = false;

    /**
     * @var mixed 数据
     */
    protected null | string | array | Throwable $value = null;
    /**
     * @var string 信息
     */
    public string $message = '' {
        get {
            return $this->message;
        }
        /** @noinspection PhpUnusedParameterInspection */
        set(string $value) {
            $this->message = $value;
        }
    }

    public function __construct(protected(set) Request $request {
        get {
            return $this->request;
        }
    }){}

    /**
     * ## 绑定处理结果
     *
     * @param array|string|null $value   值
     * @param bool              $error   错误
     * @param string|null       $message 信息
     *
     * @return void
     */
    public function complete(
        array | string | null $value = null,
        bool $error = false,
        ?string $message = null
    ): void
    {
        $this->completed = true;

        $this->setValue($value, $error);
        if ($message) $this->message = $message;
    }
    public function error(string $message): void
    {
        $this->complete(null, true, $message);
    }
    public function ok(string $message): void
    {
        $this->complete(null, false, $message);
    }

    public function setException(Throwable $e): static
    {
        $this->exception = true;
        $this->error     = true;
        $this->value     = $e;
        $this->message   = $e->getMessage();

        return $this;
    }
    public function isException(): bool
    {
        return $this->exception;
    }

    public function getValue(): string | array | Throwable | null
    {
        return $this->value;
    }
    public function setValue(array | string | null $value, bool $error = false): void
    {
        $this->error = $error;
        $this->value = $value;
    }

    /** @noinspection PhpUnused */
    public function setRedirect(string $url): void
    {
        $this->redirect = true;
        $this->complete($url);
    }
    public function isRedirect(): bool
    {
        return $this->redirect;
    }

    public function getRecords(?int $level = null): null | array
    {
        return $this->recorder?->getRecords($level ?? $this->trace_level);
    }
    public function openTrace(NameRecorder $recorder, int $level): static
    {
        $this->recorder = $recorder;
        $this->trace_level = $level;
        return $this;
    }
}